﻿package com.snakedickgames.common.box2D 
{
    import com.pblabs.engine.PBUtil;
    import com.pblabs.box2D.Box2DManagerComponent;
    import com.pblabs.engine.debug.Logger;
    import Box2D.Common.Math.b2Vec2;
    import com.pblabs.engine.entity.EntityComponent;
    import Box2D.Dynamics.Joints.b2RevoluteJoint;
    import Box2D.Dynamics.Joints.b2RevoluteJointDef;
    import Box2D.Dynamics.b2World;
    import com.pblabs.box2D.Box2DSpatialComponent;
    import com.pblabs.engine.entity.EntityComponent;
    import flash.geom.Point;
    
    // Adapted from http://pushbuttonengine.com/forum/viewtopic.php?f=5&t=163&p=2108&hilit=joint#p2108
    
    public class RevoluteJointComponent extends EntityComponent
    {
        public var spatial1:Box2DSpatialComponent = null;
        public var spatial2:Box2DSpatialComponent = null;
        public var spatialManager:Box2DManagerComponent;
        
        public var enableLimit:Boolean = true;
        public var lowerAngle:Number = 0;
        public var upperAngle:Number = 360;
        
        public var initialPosition:Point;
        
        public function get position():Point
        {
            if (joint)
            {
                var anch:b2Vec2 = joint.GetAnchor1();
                return new Point(anch.x * spatialManager.scale, 
                                anch.y * spatialManager.scale);
            }
            return null;
        }
        
        public function set enableMotor(value:Boolean):void
        {
            if (value == enableMotor)
                return;
                
            if (joint)
                joint.EnableMotor(value);
            _enableMotor = value;
        }
        
        public function get enableMotor():Boolean
        {
            return _enableMotor;
        }
        
        public function get joint():b2RevoluteJoint
        {
            return _joint;
        }
      
        public function RevoluteJointComponent()
        {
            super();
        }
        
        public function get rotation():Number
        {
            return PBUtil.getDegreesFromRadians(joint.GetJointAngle());
        }
        
        public function get motorSpeed():Number
        {
            return _joint.GetMotorSpeed();// * spatialManager.scale);
        }
        
        public function set motorSpeed(value:Number):void
        {
            return _joint.SetMotorSpeed(value);// * spatialManager.inverseScale);
        }
        
        public function get motorTorque():Number
        {
            if (_joint)
                return _joint.GetMotorTorque();// * spatialManager.scale);
            return 0;
        }
        
        public function set maxMotorTorque(value:Number):void
        {
            if (_joint)
                _joint.SetMaxMotorTorque(value);// * spatialManager.inverseScale);
        }
      
        protected override function onReset():void
        { 
            super.onReset();
            
            if (_joint != null) // joint already created
                return;            
            if (spatial1 == null)
                return;
            if (spatial2 == null)
                return;
            
            var world:b2World = spatial1.body.GetWorld();
            var jointDef:b2RevoluteJointDef = new b2RevoluteJointDef();

            jointDef.enableMotor = enableMotor;
            jointDef.enableLimit = enableLimit;
            if (enableLimit)
            {
                jointDef.lowerAngle = lowerAngle;
                jointDef.upperAngle = upperAngle;
            }
            var anchor:b2Vec2 = new b2Vec2();
            if (initialPosition != null)
            {
                anchor = new b2Vec2(initialPosition.x * spatialManager.inverseScale,
                            initialPosition.y * spatialManager.inverseScale);
            }
            else
            {
                anchor = spatial2.body.GetWorldCenter().Copy();
            }
            jointDef.Initialize(spatial1.body, spatial2.body, anchor);
            jointDef.userData = this;
            _joint = world.CreateJoint(jointDef) as b2RevoluteJoint;
        }
      
        override protected function onRemove():void 
        {
            super.onRemove();
            //spatialManager.world.DestroyJoint(_joint);
        }
        
        private var _enableMotor:Boolean = false;
        private var _joint:b2RevoluteJoint = null;
    }
}